﻿using System;
using System.Linq;

using Arquitetura.Architectural.Model;
using Arquitetura.Architectural.DataLayer;
using Arquitetura.Architectural.BusinessLogic;
using Arquitetura.DataLayer;
using Arquitetura.Model;
using Arquitetura.Common;

namespace Arquitetura.BusinessLogic
{
    internal enum AlunoOperation
    {
        Insert,
        Update,
        Delete
    }

    internal class AlunoValidation : Validation<Aluno, AlunoOperation>
    {
        #region Atributo(s)
        private readonly IAlunoData m_alunoData;
        #endregion Atributo(s)

        #region Contrutor(es)
        public AlunoValidation(Aluno aluno, AlunoOperation alunoOperation, IAlunoData alunoData)
            : base(aluno, alunoOperation)
        {
            m_alunoData = alunoData;
        }
        #endregion Contrutor(es)

        #region Método(s)
        protected override void ValidarDadosAdicionais()
        {
            switch (Operacao)
            {
                case AlunoOperation.Insert:
                    ValidarCPFValido();
                    break;

                case AlunoOperation.Update:
                    ValidarCPFValido();
                    break;

                case AlunoOperation.Delete:
                    break;

                default:
                    break;
            }
        }

        protected override void ValidarRegras()
        {
            switch (Operacao)
            {
                case AlunoOperation.Insert:
                    ValidarCPFUnico();
                    break;

                case AlunoOperation.Update:
                    ValidarExistencia();
                    ValidarCPFUnico();
                    break;

                case AlunoOperation.Delete:
                    ValidarExistencia();
                    break;

                default:
                    break;
            }
        }

        private void ValidarExistencia()
        {
            Resultado<IQueryable<Aluno>> resultado = m_alunoData.Select();
            if (resultado.Sucesso)
            {
                if (!resultado.Retorno.Where(alu => alu.Id == Target.Id).Any())
                {
                    Mensagem mensagem = new Mensagem();
                    mensagem.Entidade = "Aluno";
                    mensagem.Campo = "Id";
                    mensagem.Informacoes.Add("Registro de aluno não encotrado");
                    AdicionarResultado(false, mensagem);
                }
            }
            else
            {
                AdicionarResultado(resultado);
            }
        }

        private void ValidarCPFValido()
        {
            if (!Valida.ValidaCPF(Target.CPF))
            {
                Mensagem mensagem = new Mensagem();
                mensagem.Entidade = "Aluno";
                mensagem.Campo = "CPF";
                mensagem.Informacoes.Add("Favor preencher o campo CPF com um valor válido");
                AdicionarResultado(false, mensagem);
            }
        }

        private void ValidarCPFUnico()
        {
            Resultado<IQueryable<Aluno>> resultado = m_alunoData.Select();
            if (resultado.Sucesso)
            {
                switch (Operacao)
                {
                    case AlunoOperation.Insert:
                        if (resultado.Retorno.Where(alu => alu.CPF.Equals(Target.CPF,
                            StringComparison.InvariantCultureIgnoreCase)).Any())
                        {
                            Mensagem mensagem = new Mensagem();
                            mensagem.Entidade = "Aluno";
                            mensagem.Campo = "CPF";
                            mensagem.Informacoes.Add("Já existe outro aluno com CPF informado");
                            AdicionarResultado(false, mensagem);
                        } break;

                    case AlunoOperation.Update:
                        if (resultado.Retorno.Where(alu => (alu.Id != alu.Id) && (alu.CPF.Equals(
                            Target.CPF, StringComparison.InvariantCultureIgnoreCase))).Any())
                        {
                            Mensagem mensagem = new Mensagem();
                            mensagem.Entidade = "Aluno";
                            mensagem.Campo = "CPF";
                            mensagem.Informacoes.Add("Já existe outro aluno com CPF informado");
                            AdicionarResultado(false, mensagem);
                        } break;

                    default:
                        break;
                }
            }
            else
            {
                AdicionarResultado(resultado);
            }
        }
        #endregion Método(s)
    }
}
